package com.globalwave.pos.inventory.service;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.globalwave.common.C;
import com.globalwave.common.U;
import com.globalwave.common.exception.BusinessException;
import com.globalwave.pos.inventory.entity.InventorySO;
import com.globalwave.pos.inventory.entity.InventoryTransaction;
import com.globalwave.pos.purchase.entity.PurchasesOrderLine;
import com.globalwave.pos.sale.entity.SalesOrderLine;

import static com.globalwave.pos.inventory.entity.InventoryTransactionSO.* ;


//@Service("inventoryTransactionBO")
//@Scope("prototype")
public class InventoryTransactionBO extends InventoryBaseBO{


	public InventoryTransactionBO(String warehouseCode) {
		super.warehouseCode = warehouseCode ;
	}
	
	public Map<Long, Integer> getAvailableBalance(Long stockItemNumber) throws Exception {
		List<Long> stockItemNumbers = new ArrayList<Long>(1) ;
		stockItemNumbers.add(stockItemNumber) ;
		
		return getAvailableBalance(stockItemNumbers) ;
	}

	/**
	 * greater than 0 is availableBalance and letter than 0 is unAvailableBalance
	 * 
	 * @param stockItemNumber
	 * @param stockItemNumbers
	 * @return
	 * @throws Exception
	 */
	public Map<Long, Integer> getAvailableBalance(List<Long> stockItemNumbers) throws Exception {

		InventorySO so = new InventorySO();
		
		so.setWarehouse_code(warehouseCode) ;
		so.setStockItemNumbers(stockItemNumbers) ;
		
		List<InventoryTransaction> stockList = sumQuantityFormTransation(so) ;
			//(List<InventoryTransaction>)accessor.queryName("inventory:sumQuantityFormTransation", so) ;
		
		Map<Long, Integer> result = new HashMap<Long, Integer>();
		
		for (InventoryTransaction trans:stockList) {
			result.put(trans.getStock_item_number(), trans.getOn_hand_quantity() - trans.getMortgaged_quantity()) ;
		}
		
		return result ;
	}
	
	/**
	 * 
	 * 接口表数据移至临时表，库存数据生效(只作数量处理，不含状态处理)
	 * 
	 * @throws Exception
	 */
	public void inboundAndOutbound() throws Exception {
		//InventorySO inventorySO = (InventorySO)accessor.findName("inventory:maxInventoryTransactionInfId", null) ;
		InventorySO inventorySO = maxInventoryTransactionInfId() ;
		
		long min = inventorySO.getMin() ;
		long max = inventorySO.getMax() ;
		long id = min ;
		
		while (id < max) {
			fetchTransactionsFromInterface(inventorySO) ;
			updateInterfaceTransactionStatusToFetched(inventorySO) ;
		}
	}
	
	/**
	 * fetch all records related to order, copy records and set quantity to negative, save all records copied
	 * 
	 * @param orderNumber order number used to fetch related Transaction datas
	 */
	public void cancel(Long orderId) throws Exception {
		InventoryTransaction so = new InventoryTransaction() ;
		so.setRef_order_id(orderId) ;
		int result = jdbcDao.executeName("inventorySQLs:cancelInventoryTransaction", so) ;
		

		int updateResult1 = jdbcDao.executeName("inventorySQLs:updateTransactionStatus2Cancel", so) ;
		int updateResult2 = jdbcDao.executeName("inventorySQLs:updateTransactionHisStatus2Cancel", so) ;
		
		
		if (result != (updateResult1 + updateResult2)) {
			throw new BusinessException("two transaction update the date in the same time!!", result);
		}
		
		if (result > 1000) {
			throw new BusinessException("the records inserted to DB is too more and is unnormal!!", result);
		}
	
	}
	

	public void mortgage(SalesOrderLine orderLine) throws Exception {
		InventoryTransaction trans = new InventoryTransaction() ;
		trans.setRef_id(orderLine.getId()) ;
		trans.setRef_order_id(orderLine.getSales_order_id()) ;
		trans.setRef_uid(null) ;
		trans.setRef_source(C.REF_SOURCE_SALES_ORDER) ;
		trans.setWarehouse_code(warehouseCode) ;     
		trans.setStock_item_number(orderLine.getStock_item_number()) ;
		trans.setTransaction_code(InventoryTransaction.TRANS_CODE_MORTGAGED) ;  
		trans.setTransaction_date(U.date2int(U.currentTimestamp())) ;
		trans.setOn_hand_quantity(C.ZERO_INTEGER);
		trans.setMortgaged_quantity(orderLine.getOrder_quantity()) ;
		trans.setUnsalable_quantity(C.ZERO_INTEGER) ;
		
		trans.setStatus_(C.STATUS_ACTIVE) ;
		
		jdbcDao.insert(trans) ;
	}
	
	public void shipment(SalesOrderLine orderLine) throws Exception {		

		InventoryTransaction trans = new InventoryTransaction() ;
		trans.setRef_id(orderLine.getId()) ;
		trans.setRef_order_id(orderLine.getSales_order_id()) ;
		trans.setRef_uid(null) ;
		trans.setRef_source(C.REF_SOURCE_SALES_ORDER) ;
		trans.setWarehouse_code(warehouseCode) ;     
		trans.setStock_item_number(orderLine.getStock_item_number()) ;
		trans.setTransaction_date(U.date2int(U.currentTimestamp())) ;
		trans.setStatus_(C.STATUS_ACTIVE) ;
		
		if (!C.ZERO_INTEGER.equals(orderLine.getShipped_quantity())) {
			trans.setTransaction_code(InventoryTransaction.TRANS_CODE_SHIPMENT) ; 
			trans.setOn_hand_quantity(-orderLine.getOrder_quantity());
			trans.setMortgaged_quantity(-orderLine.getOrder_quantity()) ;
			trans.setUnsalable_quantity(C.ZERO_INTEGER) ;
			
			trans.setId(null) ;
			jdbcDao.insert(trans) ;
		}
		
	    if (!C.ZERO_INTEGER.equals(orderLine.getTna_quantity())) {// tna
			trans.setTransaction_code(InventoryTransaction.TRANS_CODE_TNA) ;  
			int shiped = orderLine.getTna_quantity() ;
			trans.setOn_hand_quantity(-shiped);
			trans.setMortgaged_quantity(-shiped) ;
			trans.setUnsalable_quantity(C.ZERO_INTEGER) ;
			
			trans.setId(null) ;
			jdbcDao.insert(trans) ;
		}
		
		
		
	}
	
	

	
	public void replenishment(PurchasesOrderLine orderLine) throws Exception {		

		InventoryTransaction trans = new InventoryTransaction() ;
		trans.setRef_id(orderLine.getId()) ;
		trans.setRef_order_id(orderLine.getPurchases_order_id()) ;
		trans.setRef_uid(null) ;
		trans.setRef_source(C.REF_SOURCE_PURCHASES_ORDER) ;
		trans.setWarehouse_code(warehouseCode) ;     
		trans.setStock_item_number(orderLine.getStock_item_number()) ;
		trans.setTransaction_date(U.date2int(U.currentTimestamp())) ;
		trans.setStatus_(C.STATUS_ACTIVE) ;
	
		trans.setTransaction_code(InventoryTransaction.TRANS_CODE_REPLENISHMENT) ; 
		trans.setOn_hand_quantity(orderLine.getOrder_quantity());
		trans.setMortgaged_quantity(C.ZERO_INTEGER) ;
		trans.setUnsalable_quantity(C.ZERO_INTEGER) ;
		
		trans.setId(null) ;
		jdbcDao.insert(trans) ;
		
	}
	
	/**
	 * 已处理数据，移至历史
	 * 
	 * @param inventorySO
	 * @throws Exception
	 */
	public void moveTransactionsToHistory(InventorySO inventorySO) throws Exception {
		jdbcDao.executeName("inventorySQLs:moveTransactionsToHistory", inventorySO) ;
	}
	
	public int deleteTempTransactions(InventorySO inventorySO) throws Exception {
		return jdbcDao.executeName("inventorySQLs:deleteTempTransactions", inventorySO) ;
	}
	
	public void fetchTransactionsFromInterface(InventorySO inventorySO) throws Exception {
		//accessor.executeName("inventory:fetchTransactionsFromInterface", inventorySO) ;
		jdbcDao.executeSQL(
				FETCH_TRANSACTIONS_FROM_INTERFACE, 
				new Object[]{
						inventorySO.getMin(), 
						inventorySO.getMax()}) ;
	}
	
	public void updateInterfaceTransactionStatusToFetched(InventorySO inventorySO) throws Exception {
		//accessor.executeName("inventory:updateInfTransStatusToFetched", inventorySO) ;
		jdbcDao.execute(
				UPDATE_INF_TRANS_STATUS_TO_FETCHED, 
				new Object[]{
						inventorySO.getMin(), 
						inventorySO.getMax()}) ;
	}
	
	public InventorySO maxInventoryTransactionId(InventorySO so) throws Exception {
		List<InventorySO> list = 
			(List<InventorySO>)jdbcDao.query(
					MAX_INVENTORY_TRANSACTION_ID, 
					null, 
					null, 
					InventorySO.class) ;
		
		if (list.size() == 0) {
			return null ;
		}
		
		return list.get(0) ;
	}
	
	public InventorySO maxInventoryTransactionInfId() throws Exception {
		
		List<InventorySO> list = 
			(List<InventorySO>)jdbcDao.query(
					MAX_INVENTORY_TRANSACTION_INF_ID,
					null, 
					null, 
					InventorySO.class) ;
		
		if (list.size() == 0) {
			return null ;
		}
		
		return list.get(0) ;
	}
	
	public List<InventoryTransaction> sumQuantityFormTransation(InventorySO so) throws Exception {
	
		return (List<InventoryTransaction>)jdbcDao.queryName("inventorySQLs:sumQuantityFormTransation", so, InventoryTransaction.class) ;
		
	}
}
